﻿/*
   Author: Tomer Paz
   BOGO.com
   2007
*/

/* the Chat client system */

package monopoly.chat {
	import fl.events.*;
	import flash.events.*;
	import fl.controls.Label;
	import fl.controls.TextArea;
	import fl.events.ComponentEvent; 
	import flash.events.TextEvent; 
	import fl.controls.ScrollPolicy;
	import fl.controls.TextInput;
	import flash.text.TextFormat;
	import flash.text.TextFieldAutoSize;
	import flash.display.Sprite;
	import flash.display.Shape;
	import flash.display.CapsStyle;
	import fl.containers.ScrollPane;
	import flash.display.Stage;
	import flash.events.EventDispatcher;
	import fl.events.ScrollEvent;
	import flash.utils.Dictionary;
	import monopoly.IFS.GLOBALS;
	import monopoly.Player.Player;
	import monopoly.Player.PlayersCollection;
	import monopoly.views.TitlePane;

	//import monopoly.CMD.ICMD;


	public class ChatClient extends ScrollPane
		{
		public static const CHAT_LOBBY:Number	= 0;
		
		protected static const VIEWSIZE:Number 	= 22;

		protected static const ACTIVE_COLOR		= 0xF000FF;
		protected static const INACTIVE_COLOR	= 0x0FF0FF;
		protected static const LOBBY_COLOR		= 0x00F000;
		
		protected const CR:int = 13;
		protected var _ChatArea:TextArea;
		protected var _ChatText:TextInput;
		protected var _Title:TitlePane;
		protected var _MyMessage:String;		// used to store last client enetered text
		protected var _playersMap:Dictionary = new Dictionary( );
		protected var _MyPlayerID:uint;
		protected var _playerSound:playerSound = new playerSound();

		//@TP - add client side buffer overflow prevention:
		public const MAX_TEXT_LENGTH 		= 256;
		
		protected var _defaultWidth:Number 	= 205;
		protected var _defaultHeight:Number = 140;
		protected var _tf:TextFormat;
		protected var _lastScrollPosition:Number = 0;
		protected var _nextX:Number;

			
		public function ChatClient(myPlayerID:uint)
			{
			_MyPlayerID = myPlayerID;
			_nextX = x;
			
			/* setup components */
			
			setupTitle();
			
			setupChatArea();
			
			var lobbySprite:Sprite = addLobbySprite();

			/* push in First location (0) the "Main" chat area ("Lobby") */
			
			var ChatAndSprite:Array = new Array(_ChatArea, lobbySprite);
			_playersMap [ CHAT_LOBBY ] = ChatAndSprite;
			
			setupChatText();
			
			/* add event listeners to text message */
			
			_ChatText.addEventListener(ComponentEvent.ENTER, clickedEnter);
			_ChatText.addEventListener(TextEvent.TEXT_INPUT, enterText);

			with (this)
				{
				width = _defaultWidth;
				height = _defaultHeight;
				//opaqueBackground = GLOBALS.DEFAULT_DIALOG_COLOR;
				}
				
			setActiveChatArea(CHAT_LOBBY);
			}

		/* public interface */
			
		public function WriteMessage(name:String, SenderID:int, rcptID:int, msg:String):void
			{
			/* set chatClient correct chat tab */
			
			if (SenderID != _MyPlayerID)
				{
				if (rcptID == CHAT_LOBBY)
					this.setActiveChatArea(rcptID);
				else
					this.setActiveChatArea(SenderID);
				}
			
			
			// if not the first line	
			if ( _ChatArea.length )
				{
				// in order to overcome TextArea auto-move of scroll position...
				var tmpPosition:Number = _lastScrollPosition;
				_ChatArea.appendText("\r\n");
				_lastScrollPosition = tmpPosition;
				}

			_ChatArea.appendText(name + ": " + msg);
			}
			
		public function get MyMsg():String
			{
			return (_MyMessage);
			}

		public function get ChatArea():TextArea
			{
			return _ChatArea;
			}
		public function get ChatText():TextInput
			{
			return _ChatText;
			}
			
		/* add player to chat GUI */
		
		public function addPlayer(player:Player):void
			{
			var pSprite:Sprite;
			
			/* case Empty user */
			
			if (null == player)
				{
				/* add Only button for Empty player */
				
				pSprite = addPlayerSprite(player);
				return;
				}
			
			/* case my player */
			
			if (player.ID == _MyPlayerID)
				return;
				
			/* other player */
			
			setupChatArea();
			
			/* add button for player tab */
			
			pSprite = addPlayerSprite(player);
			
			/* add to map of chat tabs */
			
			_playersMap [ player.ID ] = new Array(_ChatArea, pSprite);
			}
		public function removePlayer(player:Player):void
			{
			_playersMap [ player.ID ] = undefined;
			}
		public function onPlayerChange(e:Event):void
			{
			var players:PlayersCollection = e.currentTarget as PlayersCollection;
			
			if (e.type == Event.ADDED)
				{
				addPlayer(players.lastHandeledPlayer);
				if (GLOBALS.DEBUG & GLOBALS.DEBUG_LOGIC)
					{
					var p:String = (null != players.lastHandeledPlayer) ? players.lastHandeledPlayer.Name : "Empty";
					trace("[ChatClient][onPlayerChange] added player: " + p + " to Chat");
					}
				}
			else if (e.type == Event.REMOVED)
				{
				removePlayer(players.lastHandeledPlayer);
				}
			}
		
		public function setActiveChatArea(playerID:uint):void
			{
			/* hide Current chat area if necessary */
			
			if (_ChatArea == _playersMap [ playerID ][0])
				return;
				
			bringToBack();
			
			/* set selected chat area */
			
			_ChatArea = _playersMap [ playerID ][0];
			
			/* expose selected chat area */
			
			bringToFront();
			}
			
		/* return active player ID by current active chat tab */
		
		public function get ActiveChatPlayerID():uint
			{
			var ret:uint = 0;		// default "ALL"
			
			for (var key:Object in _playersMap)
				{
				if (_playersMap [ key ][0] == _ChatArea)
					{
					ret = key as uint;
					break;
					}
				}
			return ret;
			}
			
		public override function set height(value:Number):void
			{
			super.height = value;
			
			var chatArea:TextArea;
			for (var key:Object in _playersMap)
				{
				chatArea = (_playersMap [ key ] as Array)[0];
				chatArea.height = value - VIEWSIZE*3 - 4;
				}
			_ChatText.y	= chatArea.y + chatArea.height + 2;
			}
		public override function set width(value:Number):void
			{
			_Title.width = value -1;
			
			var chatArea:TextArea;
			for (var key:Object in _playersMap)
				{
				chatArea = (_playersMap [ key ] as Array)[0];
				chatArea.width = value - 3;
				}
			_ChatText.width	= value - 3;
			
			super.width = value;
			}
			
		public function set Enable(status:Boolean):void
			{
			_ChatText.enabled = status;
			}

		/* private members */
		
		protected function bringToBack():void
			{
			_ChatArea.visible = false;
			}
		protected function bringToFront():void
			{
			_ChatArea.visible = true;
			this.setChildIndex(_ChatArea,this.numChildren-1);
			}

			
		protected function enterText(e:TextEvent):void
			{
			// "e" is actually _ChatText.textField -> only the character that was pressed right now
			if ( _ChatText.text.search(/type your message here/) != -1 )
				{
				_ChatText.text = "";
				_ChatText.validateNow();
				_ChatText.drawNow();
				}
			//@TP - add client side buffer overflow prevention:
			if ( _ChatText.text.length > MAX_TEXT_LENGTH )
				{
				// cancel last character entered
				_ChatText.text.replace(/?$/, "");
				}
			}
			
		// user clicked Enter			
		protected function clickedEnter(e:ComponentEvent):void
			{
			//empty input will not trigger anything
			if ( _ChatText.text != "" )
				{
				WriteMessage("me", _MyPlayerID, ActiveChatPlayerID, _ChatText.text);
				_MyMessage = _ChatText.text;
				
				_ChatText.text = "";
				_ChatText.validateNow();
				_ChatText.drawNow();

				_ChatArea.verticalScrollPosition = _lastScrollPosition;
				_ChatArea.verticalScrollBar.update();

				/* dispatch message */
				
				dispatchEvent(e);
				}
			}
		
		protected function setupTitle():void
			{
			_Title = new TitlePane("Chat");
			_Title.x = 1;
			_Title.y = 3;
			_Title.width = width - 1;
			
			addChild(_Title);
			}
			
		protected function setupChatArea():void
			{
			setupTF();
			_ChatArea = new TextArea();
			_ChatArea.textField.defaultTextFormat = _tf;
			//_ChatArea.textField.autoSize = TextFieldAutoSize.LEFT;
			
			_ChatArea.height = _defaultHeight - VIEWSIZE - 10;
			_ChatArea.width  = _defaultWidth - 5;
			_ChatArea.setSize(_ChatArea.width, _ChatArea.height);
			_ChatArea.verticalScrollPolicy = ScrollPolicy.AUTO;
			_ChatArea.verticalScrollBar.height = _ChatArea.height - 20;
			_ChatArea.verticalScrollBar.enabled = true;
			_ChatArea.verticalScrollBar.pageSize = 8;
			_ChatArea.y = VIEWSIZE*2 + 2;
			_ChatArea.x = 2;
	
			_ChatArea.editable = false;
			
			_ChatArea.addEventListener(ScrollEvent.SCROLL, scrollHandler);
			addChild(_ChatArea);
			}
		protected function setupTF():void
			{
			if (null == _tf)
				{
				_tf = new TextFormat("Courier",10);
				_tf.letterSpacing = 1;
				}
			}
			
		protected function setupChatText():void
			{
			setupTF();
			_ChatText = new TextInput();
			
			_ChatText.textField.defaultTextFormat = _tf;
			_ChatText.width  = _defaultWidth - 5;
			_ChatText.height = 28;

			_ChatText.maxChars = 255;
			_ChatText.textField.background = true;
			_ChatText.textField.border	   = true;

			//_ChatText.verticalScrollPolicy = ScrollPolicy.OFF;
			_ChatText.textField.multiline  = false;
			
			_ChatText.text = "type your message here";
			_ChatText.drawFocus(true);
			_ChatText.x		= 1;
			_ChatText.y		= VIEWSIZE + _defaultHeight + 1;
			
			_ChatText.enabled = false;
			
			addChild(_ChatText);
			}

		protected function addLobbySprite():Sprite
			{
			var sprite:Sprite = new Sprite();
			sprite.buttonMode = true;
			sprite.x		  = 0;
			sprite.y		  = 0;
			
			var shape:Shape	  = new Shape();
			
			shape.y = VIEWSIZE;
			
			with (shape.graphics) //sprite.graphics) 
				{
				lineStyle(3, ACTIVE_COLOR, 1, false, "normal", CapsStyle.ROUND);
				beginFill(LOBBY_COLOR, 0.5);
		        drawCircle(VIEWSIZE/2, VIEWSIZE/2, VIEWSIZE/2);
				endFill();
				}
			//sprite.width	  = VIEWSIZE + 5;
			sprite.addChild(shape);
			
			addStatusBox("Lobby", sprite);
			
			_nextX = sprite.x + VIEWSIZE + 3;
			
			sprite.addEventListener(MouseEvent.CLICK, onSpriteClick);
			sprite.addEventListener(MouseEvent.MOUSE_OVER, onSpriteOver);
			sprite.addEventListener(MouseEvent.MOUSE_OUT, onSpriteOut);

			addChild(sprite);
			return sprite;
			}
		protected function addPlayerSprite(player:Player):Sprite
			{
			var psprite:Sprite = new Sprite();
			psprite.buttonMode = true;
			psprite.x		   = _nextX;
			psprite.y		   = 0;

			var shape:Shape = new Shape();
			
			shape.y = VIEWSIZE;
			
			with (shape.graphics)
				{
				lineStyle(3, INACTIVE_COLOR, 1, false, "normal", CapsStyle.ROUND);
				beginFill((null != player) ? GLOBALS.PCOLORS[player.ID - 1] : INACTIVE_COLOR, 0.5);
		        drawCircle(VIEWSIZE/2, VIEWSIZE/2, VIEWSIZE/2);
				endFill();
				}
			psprite.addChild(shape);
			
			addStatusBox((null != player) ? player.Name : "Empty", psprite);
			
			_nextX = _nextX + VIEWSIZE + 3;
			
			if (null != player)
				{
				psprite.addEventListener(MouseEvent.CLICK, onSpriteClick);
				}
			psprite.addEventListener(MouseEvent.MOUSE_OVER, onSpriteOver);
			psprite.addEventListener(MouseEvent.MOUSE_OUT, onSpriteOut);
			psprite.visible = true;
			
			addChild(psprite);
			return(psprite);
			}

		protected function addStatusBox(Title:String, sprite:Sprite):void
			{
			var tlabel:Label = new Label();
			
			//sprite.width += 25;
			tlabel.text = Title;
			//tlabel.setSize(25, 20);
			tlabel.autoSize = TextFieldAutoSize.LEFT;
			tlabel.x = 0;
			tlabel.y = 0;
			tlabel.visible = false;
			
			sprite.addChild(tlabel);
			}

		protected function StatusDraw(tlabel:Label):void
			{
			//this.setChildIndex(tlabel.parent,this.numChildren-1);
			tlabel.visible = true;
			}
		protected function StatusUnDraw(tlabel:Label):void
			{
			tlabel.visible = false;
			}
			
		protected function scrollHandler(event:ScrollEvent):void 
			{
			_lastScrollPosition = event.position;
			}
		
		protected function onSpriteClick(me:MouseEvent):void
			{
			var sprite:Sprite = me.target as Sprite;
			
			/* play sound */
			
			_playerSound.play();
			
			/* locate relevant chatArea to show */
			var shape:Shape;
			for (var key:Object in _playersMap)
				{
				shape = ((_playersMap [ key ] as Array)[1]).getChildAt(0) as Shape;
				var id:uint = key as uint;
				
				if ((_playersMap [ id ] as Array)[1] == sprite)
					{
					with (shape.graphics)
						{
						lineStyle(3, ACTIVE_COLOR, 1, false, "normal", CapsStyle.ROUND);
						beginFill((id == CHAT_LOBBY) ? LOBBY_COLOR : GLOBALS.PCOLORS[id - 1], 0.5);
						drawCircle(VIEWSIZE/2, VIEWSIZE/2, VIEWSIZE/2);
						endFill();
						}
					setActiveChatArea(id);
					//break;
					}
				else
					{
					with (shape.graphics)
						{
						lineStyle(3, INACTIVE_COLOR, 1, false, "normal", CapsStyle.ROUND);
						beginFill((id == CHAT_LOBBY) ? LOBBY_COLOR : GLOBALS.PCOLORS[id - 1], 0.5);
						drawCircle(VIEWSIZE/2, VIEWSIZE/2, VIEWSIZE/2);
						endFill();
						}
					}
				}
			}
		protected function onSpriteOver(me:MouseEvent):void
			{
			var sprite:Sprite = me.currentTarget as Sprite;
			StatusDraw(sprite.getChildAt(1) as Label);
			}
		protected function onSpriteOut(me:MouseEvent):void
			{
			var sprite:Sprite = me.currentTarget as Sprite;
			StatusUnDraw(sprite.getChildAt(1) as Label);
			}
			
		}
	
}